<template>
  <div>
    <div class="upload-file">
      <el-upload
        multiple
        :action="uploadFileUrl"
        :before-upload="handleBeforeUpload"
        :file-list="fileList"
        :limit="limit"
        :on-error="handleUploadError"
        :on-exceed="handleExceed"
        :on-success="handleUploadSuccess"
        :show-file-list="false"
        :headers="headers"
        class="upload-file-uploader"
        ref="fileUpload"
      >
        <!-- 上传按钮 -->
        <el-button size="mini" type="primary"  >选取文件</el-button>
        <!-- 上传提示 -->
        <div class="el-upload__tip" slot="tip" v-if="showTip">
          请上传
          <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
          <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
          的文件
        </div>
      </el-upload>

      <!-- 文件列表 -->
      <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
        <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">


          <el-row :gutter="18" style="width: 100%;">
            <el-col :span="18">
              <el-button  @click="handlePreview(file)" type="text">
                {{ getFileName(file.originalName) }}
              </el-button>
            </el-col>
            <el-col :span="6">
              <div style="display: flex; align-items: center; gap: 10px;">
                <el-link :underline="false" @click="handleDownload(file)" type="primary"> 下载</el-link>
                <el-link :underline="false" @click="handleDelete(index)" type="danger"> 删除</el-link>
              </div>
            </el-col>

        </el-row>
        </li>
      </transition-group>
    </div>

    <el-dialog
      :visible.sync="previewVisible"
      :fullscreen="isFullscreen"
      @close="handlePreviewClose"
      class="preview-dialog"
    >
      <div class="preview-container">
        <!-- PDF预览 -->
         <pdf-preview
          v-if="previewType === 'pdf'"
          :file-url="previewUrl"
          :current-page.sync="currentPage"
          :total-pages="totalPages"
          @toggle-fullscreen="toggleFullscreen"
        />


        <!-- 图片预览 -->
        <image-preview
          v-else-if="previewType === 'image'"
          :src="previewUrl"
          :is-loading="isLoading"
          :is-fullscreen="isFullscreen"
          @toggle-fullscreen="toggleFullscreen"
        />

        <vue-office-preview
          v-else-if="previewType === 'office'"
         :src="officePreviewUrl"
         :file-ext="previewFileExt"
         :originalSrc="officeOriginalUrl"
         :is-fullscreen="isFullscreen"
          @toggle-fullscreen="toggleFullscreen"
        />

        <!-- 文本预览 -->
        <text-preview
          v-else-if="previewType === 'text'"
          :content="previewContent"
          :is-loading="isLoading"
          :is-fullscreen="isFullscreen"
           @toggle-fullscreen="toggleFullscreen"
        />

        <!-- 不支持的类型 -->
        <div v-else class="unsupported-type">
          暂不支持此文件类型的预览
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from "@/utils/auth";
import { downloadMinioFile,previewFile } from '@/api/common/common';

// 新增组件引入
import PdfPreview from './PdfPreview.vue'
import ImagePreview from './ImagePreview.vue'
import OfficePreview from './OfficePreview.vue'
import TextPreview from './TextPreview.vue'
import axios from 'axios';
import VueOfficePreview from './VueOfficePreview.vue'
// import PdfViewer from './PdfViewer.vue'

export default {
  name: "FileUpload",
  dicts: ['sci_file_type'],
  filters: {
    formatDate(value) {
      if (!value) return '';
      const date = new Date(value);
      return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`;
    }
  },
  props: {
    // 值
    value: [String, Object, Array],
    // 数量限制
    limit: {
      type: Number,
      default: 1,
    },
    // 大小限制(MB)
    fileSize: {
      type: Number,
      // default: 5,
    },
    // 文件类型, 例如['png', 'jpg', 'jpeg']
    fileType: {
      // type: Array,
      // default: () => ["doc", "xls", "ppt", "txt", "pdf"],
    },
    // 是否显示提示
    isShowTip: {
      type: Boolean,
      default: true
    }
  },
  components: {
    PdfPreview,
    ImagePreview,
    OfficePreview,
    TextPreview,
    VueOfficePreview,
    // PdfViewer
  },
  data() {
    return {
      number: 0,
      uploadList: [],
      baseUrl: process.env.VUE_APP_BASE_API,
      uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/uploadMinio", // 上传文件服务器地址
      headers: {
        Authorization: "Bearer " + getToken(),
      },
      fileList: [],// 数据结构变更为[{ originalName, newFileName, Url, datetime, uid }]

      previewVisible: false,
      previewType: '',
      previewUrl: '',
      previewContent: '',
      officePreviewUrl: '',
      officeOriginalUrl: '',
      currentPage: 1,
      totalPages: 0,
      isLoading: false,
      isFullscreen: false,
      // 预览缓存（使用内存缓存）
      previewCache: new Map(),
      previewFileExt: '',  // 记录当前预览文件的扩展名
      noUpload: true,
    };
  },
  watch: {
    // fileList: {
    //   handler(newVal) {
    //     this.$emit("input", this.listToString(newVal));
    //   },
    //   deep: true
    // },
    value: {
      handler(val) {
        if (val) {
          let temp = 1;
          try {
            const list = typeof val === 'string' ? JSON.parse(val) : val;
            this.fileList = list.map(item => ({
              uid: item.uid || Date.now() + temp++,
              originalName: item.originalName || this.parseFileName(item.url),
              fileName: item.fileName || this.parseFileName(item.url),
              url: item.url || item.url,
              datetime: item.datetime || new Date().toISOString(),
              fileSize: item.fileSize || 0,
              fileExtension: item.fileExtension || ''
            }));
          } catch (e) {
            this.fileList = [];
          }
        } else {
          this.fileList = [];
        }
      },
      deep: true,
      immediate: true
    }
  },
  computed: {
    // 是否显示提示
    showTip() {
      return this.isShowTip && (this.fileType || this.fileSize);
    },
  },
  methods: {
    // 上传前校检格式和大小
    handleBeforeUpload(file) {
      // 校检文件类型
      if (this.fileType) {
        const fileName = file.name.split('.');
        const fileExt = fileName[fileName.length - 1];
        const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
        if (!isTypeOk) {
          this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
          return false;
        }
      }
      // 校检文件大小
      if (this.fileSize) {
        const isLt = file.size / 1024 / 1024 < this.fileSize;
        if (!isLt) {
          this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
          return false;
        }
      }
      this.$modal.loading("正在上传文件，请稍候...");
      this.number++;
      return true;
    },
    // 文件个数超出
    handleExceed() {
      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
    },
    // 上传失败
    handleUploadError(err) {
      this.$modal.msgError("上传文件失败，请重试");
      this.$modal.closeLoading();
    },


    handleUploadSuccess(res, file) {
      if (res.code === 200) {
        this.uploadList.push({
          originalName: res.originalFilename,
          fileName: res.newFileName,
          url: res.fileUrl || res.fileName, // 根据实际返回字段调整
          datetime: this.getBeijingTimeISOString(),
          uid: Date.now(),
          fileClass: '', // 初始化为空字符串
          remark: '', // 初始化为空字符串

          fileSize: file.size,          // 文件字节大小
          fileExtension: res.originalFilename.split('.').pop().toLowerCase() // 文件扩展名
        });
        this.uploadedSuccessfully();
      } else {
        // 错误处理逻辑保持不变
      }
    },
    // 对象转JSON字符串
    listToString(list) {
      return JSON.stringify(list.map(item => ({
        originalName: item.originalName,
        fileName: item.fileName,
        url: item.url,
        datetime: item.datetime,
        fileSize: item.fileSize,
        fileExtension: item.fileExtension
      })));
    },

    // 辅助方法：从URL解析文件名
    parseFileName(url) {
      if (!url) return '';
      const segments = url.split('/');
      return segments[segments.length - 1];
    },
    // 删除文件
    handleDelete(index) {
      // this.fileList.splice(index, 1);
      // this.$emit("input", this.listToString(this.fileList));

      const newFileList = this.fileList.filter((_, i) => i !== index);
      this.noUpload= true
      this.$emit('input', this.listToString(newFileList)); // 始终 emit 新数组
    },
    // 上传结束处理
    uploadedSuccessfully() {
      if (this.number > 0 && this.uploadList.length === this.number) {
        this.fileList = this.fileList.concat(this.uploadList);
        this.uploadList = [];
        this.number = 0;
        this.$emit("input", this.listToString(this.fileList));
        // 触发 datetime 更新事件
        this.$emit('update:datetime', this.getBeijingTimeISOString(),);
        this.$modal.closeLoading();
        this.noUpload= false
      }
    },

    // 获取北京时间 ISO 字符串的方法
    getBeijingTimeISOString() {
      const now = new Date();
      const offset = 8; // 北京时间是 UTC+8
      const beijingTime = new Date(now.getTime() + (offset * 60 * 60 * 1000));
      return beijingTime.toISOString();
    },
    // 获取文件名称
    getFileName(name) {
      // 如果是url那么取最后的名字 如果不是直接返回
      if (name.lastIndexOf("/") > -1) {
        return name.slice(name.lastIndexOf("/") + 1);
      } else {
        return name;
      }
    },
    // 对象转成指定字符串分隔
    // listToString(list, separator) {
    //   let strs = "";
    //   separator = separator || ",";
    //   for (let i in list) {
    //     strs += list[i].url + separator;
    //   }
    //   return strs != '' ? strs.substr(0, strs.length - 1) : '';
    // },

    handleDownload(file) {
      const fileName = file.url; // 替换为实际的文件名
      downloadMinioFile(fileName);
    },


    // 处理预览关闭
    handlePreviewClose() {
      this.previewContent = ''
      this.currentPage = 1
      this.totalPages = 0
      this.isFullscreen = false
      this.officeOriginalUrl = ''
    },

    // 切换全屏模式
    toggleFullscreen() {
      this.isFullscreen = !this.isFullscreen
    },

    // 文件预览处理
    async handlePreview(file) {
      try {
        const fileExt = this.getFileExtension(file.originalName)
        this.previewFileExt = fileExt  // 记录文件类型
        this.officeOriginalUrl = file.url
        const cachedPreview = this.checkPreviewCache(file.url)

        if (cachedPreview) {
          this.handleCachedPreview(cachedPreview, fileExt)
          return
        }

        this.isLoading = true

        const previewData = await this.fetchPreviewData(file, fileExt)
        this.setupPreview(previewData, fileExt)
        this.cachePreview(file.url, previewData)
      } catch (error) {
        this.handlePreviewError(error)
      } finally {
        this.isLoading = false
        this.previewVisible = true
      }
    },

    // 获取文件扩展名
    getFileExtension(filename) {
      return filename.split('.').pop().toLowerCase()
    },

    // 检查预览缓存
    checkPreviewCache(fileUrl) {
      return this.previewCache.get(fileUrl)
    },

    // 缓存预览数据
    cachePreview(fileUrl, data) {
      this.previewCache.set(fileUrl, data)
    },

    // 处理缓存命中
    handleCachedPreview(cachedData, fileExt) {
      this.setupPreview(cachedData, fileExt)
      this.previewVisible = true
    },

    // 获取预览数据
    async fetchPreviewData(file, fileExt) {
      const handlers = {
        pdf: this.handlePdfPreview,
        image: this.handleImagePreview,
        office: this.handleOfficePreview,
        text: this.handleTextPreview
      }

      const type = this.getFileType(fileExt)
      return handlers[type](file)
    },

    // 获取文件类型分类
    getFileType(ext) {
      if (['pdf'].includes(ext)) return 'office'
      if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext)) return 'image'
      // if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(ext)) return 'office'
      if (['docx', 'xlsx', 'pptx'].includes(ext)) return 'office' // 只支持新格式
      return 'text'
    },

    // 处理PDF预览
    async handlePdfPreview(file) {
      return {
        type: 'pdf',
        url: await this.generateSecureUrl(file)
      }
    },

    // 处理图片预览
    async handleImagePreview(file) {
      return {
        type: 'image',
        url: await this.generateSecureUrl(file)
      }
    },

    // 处理Office预览（使用微软在线服务）
    async handleOfficePreview(file) {
      // const encodedUrl = encodeURIComponent(await this.generateSecureUrl(file))
      return {
        type: 'office',
        // url: `https://view.officeapps.live.com/op/embed.aspx?src=${encodedUrl}`
        url: await this.generateSecureUrl(file) // 直接使用 Minio 预签名地址
      }
    },

    // 处理文本预览
    async handleTextPreview(file) {
      try {
        const secureUrl = await this.generateSecureUrl(file);
        const response = await axios.get(secureUrl, {
          responseType: 'text',
          transformResponse: [data => data]
        });
        return {
          type: 'text',
          content: response.data
        };
      } catch (error) {
        console.error('处理文本预览失败:', error);
        throw error;
      }
    },

   // 生成安全访问链接
    async generateSecureUrl(file) {
        const response = await previewFile(file.url);
        // if (response.code === 200) {
        return response.fileUrl;

    },

    // 初始化预览
    setupPreview(data, fileExt) {
      this.previewType = data.type
      if (data.type === 'office') {
        this.officePreviewUrl = data.url
      } else if (data.type === 'text') {
        this.previewContent = data.content
      } else {
        this.previewUrl = data.url
      }
    },

    // 处理预览错误
    handlePreviewError(error) {
      console.error('Preview error:', error)
      this.$message.error('文件预览失败：' + error.message)
    }


  }
};
</script>

<style scoped lang="scss">
.upload-file-uploader {
  margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {
  border: 1px solid #e4e7ed;
  line-height: 2;
  margin-bottom: 10px;
  position: relative;
}
.upload-file-list .ele-upload-list__item-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: inherit;
}
.ele-upload-list__item-content-action .el-link {
  margin-right: 10px;
}
.preview-dialog {
  ::v-deep .el-dialog__body {
    padding: 0;
    height: 80vh;
    display: flex;
    flex-direction: column;
  }
}

.preview-container {
  flex: 1;
  overflow: auto;
  position: relative;
}

.unsupported-type {
  padding: 50px;
  text-align: center;
  color: #999;
}
</style>
